﻿// INGENIOUS FRAMEWORK - Semantic Web Development Simplified
// Copyright (C) 2012 Linked Data Tools

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>

// Based on the LinqToXSD NameMangler routines, licensed under the
// Microsoft Public License found at http://linqtoxsd.codeplex.com/license.

// Portions of this sourcecode are (c) Copyright Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using System.Globalization;
using System.Xml.Serialization;

namespace Ingenious.Owl.Linq
{
    public enum NameOptions
    {
        None,
        MakeCollection,
        MakeList,
        MakePlural,
        MakeField,
        MakeParam,
        MakeLocal,
        MakeUnion,
        MakeDefaultValueField,
        MakeFixedValueField,
    }

    public static class NameGenerator
    {
        static int uniqueIdCounter = 0;
        static Hashtable keywords;

        static NameGenerator()
        {
            keywords = new Hashtable();
            string [] keywordlist = 
            { "abstract","event","new", "struct","as","explicit","null","switch",
            "base","extern","object","this","bool","false","operator","throw",
            "break","finally","out","true","byte","fixed","override","try","case",
            "float","params","typeof","catch","for","private","uint","char","foreach",
            "protected","ulong","checked","goto","public","unchecked","class",
            "if","readonly","unsafe","const","implicit","ref","ushort","continue",
            "in","return","using","decimal","int","sbyte","virtual","default",
            "interface","sealed","volatile","delegate","internal","short","void",
            "do","is","sizeof","while","double","lock","stackalloc","else","long",
            "static","enum","namespace","string","var"};
 
            foreach(string k in keywordlist)
            {
                keywords.Add(k.ToUpper(CultureInfo.InvariantCulture), k);
            }
        }

        public static int GetUniqueID()
        {
            Interlocked.Increment(ref uniqueIdCounter);
            return uniqueIdCounter;
        }

        public static string ChangeClrName(string clrName, NameOptions options)
        {
            switch(options)
            {
            case NameOptions.MakeCollection:
                if (clrName[0] == '@') {
                    clrName = clrName.Remove(0,1);
                }
                return clrName + "Collection";

            case NameOptions.MakeList:
                return clrName + "List";

            case NameOptions.MakePlural:
                return clrName + "s";

            case NameOptions.MakeField:
                return clrName + "Field";

            case NameOptions.MakeLocal:
                return clrName + "LocalType";

            case NameOptions.MakeUnion:
                return clrName + "UnionValue";

            case NameOptions.MakeFixedValueField:
                return clrName + "FixedValue";

            case NameOptions.MakeParam:
                return clrName + "Param";
                    
            case NameOptions.MakeDefaultValueField:
                return clrName + "DefaultValue";
            }

            return clrName;
        }

        public static string MakeValidCLRNamespace(string xsdNamespace, bool nameMangler2)
        {
            if (xsdNamespace == null || xsdNamespace == string.Empty)
            {
                return string.Empty;
            }

            xsdNamespace = xsdNamespace.Replace("http://", string.Empty);

            if(xsdNamespace == string.Empty)
            {
                return string.Empty;
            }

            if (nameMangler2)
            {
                xsdNamespace = xsdNamespace.Replace('.', '_').Replace('-', '_');
            }

            string[] pieces = xsdNamespace.Split(new char[] { '/', '.', ':', '-' });

            string clrNS = NameGenerator.MakeValidIdentifier(pieces[0]);

            for (int i =1; i< pieces.Length; i++)
            {
                if (pieces[i] != string.Empty)
                {
                    clrNS = clrNS + "." + NameGenerator.MakeValidIdentifier(pieces[i]);
                }
            }

            return clrNS;
        }

        public static string MakeValidIdentifier(string identifierName)
        {
            identifierName = CodeIdentifier.MakeValid(identifierName);

            if (IsKeyword(identifierName))
            {
                return "@" + identifierName;
            }

            return identifierName;
        }

        public static bool IsKeyword(string identifier)
        {
            return keywords.ContainsKey(identifier.ToUpper(CultureInfo.InvariantCulture));
        }
    }
}
